<--- %%NOBANNER%% --> _array.sas
 BackForward

/*-------------------<-- Start of Description -->--------------------\
| Declare an array;                                                  |
|--------------------<--- End of Description -->---------------------|
|--------------------------------------------------------------------|
|--------------<--- Start of Files or Arguments Needed -->-----------|
| Arguments Required:                                                |
|    array - the name of an array;                                   |
|    dim1  - the first dimension of the array;                       |
| Arguments:                                                         |
|    dim2   - the 2nd dimension of the array (2 or more dimensional);|
|    dim3   - the 3rd dimension of the array (3 or more dimensional);|
|    attrib - the attribution of the created array;                  |
|    default- the initial value of the array;                        |
|    var    - the variable name: default is the name of the array;   |
|    length - the length of each variable in the created array;      |
|    suffix - the suffix of different dimension of the array names;  |
|---------------<--- End of Files or Arguments Needed -->------------|
|--------------------------------------------------------------------|
|----------------<--- Start of Example and Usage -->-----------------|
| Example:                                                           |
|  data one;                                                         |
|    %_array(array=mln, dim1=2, dim2=2, dim3=3, suffix=2,default=0); |
|  run; %print(one);                                                 |
|  data two;                                                         |
|     %_array(array=mln, dim1=1986:1998, dim2=12, default=0);        |
|  run; %print(two);                                                 |
| Usage: %_array(array=, dim1=, dim2=, dim3=, attrib=, default=,     |
|                var=&array, length=, suffix=);                      |
\-------------------<--- End of Example and Usage -->---------------*/
%macro _array(array=, dim1=, dim2=, dim3=, w1=, w2=, w3=,attrib=, 
              default=, var=&array, length=, suffix=);
/*--------------------------------------------\
| Author:   Duo Zhou;                         |
| Created:  3-23-2001 5:12pm;                 |
| Purpose:  Array Creator;                    |
\--------------------------------------------*/
%local _i_ i j k max mult return;
%if (%quote(&array) eq) or (%quote(&dim1) eq) %then %do;
   %if (%quote(&array) eq) %then %do;
      %put ==> Error: This is not a valid array!; 
   %end;
   %if (%quote(&dim1) eq) %then %do;
      %put ==> Error: I need a valid dimensiony!; 
   %end;
   %goto finish;
%end;
%let _i_=0;
%do %while(%length(%nrbquote(%scan(%quote(&dim1 &dim2 &dim3), %eval(&_i_+1), %str( )))));
   %let _i_=%eval(&_i_+1);
%end;
%let max=&_i_;
%do i=1 %to &max;
    %local lo&i hi&i len&i mod&i;
    %let lo&i=%scan(&&dim&i, 1, :);
    %let hi&i=%scan(&&dim&i, 2, :);

    %if %length(&&hi&i)=0 %then %do;
        %let hi&i=&&lo&i;
        %let lo&i=1;
    %end;
%end;
%do i=1 %to &max; 
    %let return=&return &&lo&i:&&hi&i;
    %if &i<&max %then %let return=&return,; 
%end;
%let return=array &array(&return) &length;
%do i=1 %to &max;
    %if %length(&&w&i) %then %do;
        %let lo&i=%_substr(&&lo&i, %length(&&lo&i)-&&w&i+1);
        %let hi&i=%_substr(&&hi&i, %length(&&hi&i)-&&w&i+1);
    %end;
    %else %do;
        %let mod&i=%eval(&&hi&i-&&lo&i);
        %let mod&i=%sysfunc(log10(&&mod&i));
        %let mod&i=%sysfunc(ceil(&&mod&i));
        %let mod&i=%_max(%eval(10**&&mod&i), 10);

        %if %sysfunc(mod(&&lo&i, &&mod&i))< %sysfunc(mod(&&hi&i, &&mod&i))
        %then %do;
            %let lo&i=%sysfunc(mod(&&lo&i, &&mod&i));
            %let hi&i=%sysfunc(mod(&&hi&i, &&mod&i));
        %end;
    %end;
    %let len&i=%length(&&hi&i);
%end;
%do i=&lo1 %to &hi1; 
    %let dim1=&var%_repeat(0, &len1-%length(&i))&i;
    %if &max>1 %then %do j=&lo2 %to &hi2;
        %let dim2=%_repeat(0, &len2-%length(&j))&j;

        %if &max=3 %then %do k=&lo3 %to &hi3;
            %let dim3=%_repeat(0, &len3-%length(&k))&k;
            %let return=&return &dim1.&dim2.&dim3.&suffix; %put &return;
        %end;
        %else %let return=&return &dim1.&dim2.&suffix;
    %end;
    %else %let return=&return &dim1.&suffix;
%end;
%if %length(&default) %then %do;
    %put WARNING: Specifying initial values with an ARRAY statement;
    %put WARNING: causes the variables to be RETAINed!.  If you want;
    %put WARNING: to modify this behavior, see the _RETAIN macro.;
    %put;
    %if %index(&default, %str(%()) %then &default;
    %else %do;
        %let mult=%eval(&hi1-&lo1+1);
        
        %if &max>1 %then %let mult=%eval(&mult*(&hi2-&lo2+1));
        %if &max=3 %then %let mult=%eval(&mult*(&hi3-&lo3+1));

        %let return=&return (&mult*&default);
    %end;
%end;&return
%if %length(&attrib) %then %do; 
   %let _i_=0;
   attrib 
   %do %while(%length(%nrbquote(%scan(%quote(&return), %eval(&_i_+1), %str( )))));
      %let _i_=%eval(&_i_+1);
      %scan(%quote(&return), &_i_, %str( ));
   %end; &attrib;
%end;;
%finish:
%mend _array;